package com.ringtheweb.web.action;

import java.io.Serializable;
import java.util.Date;

import org.hibernate.validator.Email;
import org.hibernate.validator.InvalidStateException;
import org.hibernate.validator.InvalidValue;
import org.hibernate.validator.Length;
import org.hibernate.validator.NotNull;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;

import com.ringtheweb.model.PhoneNumber;
import com.ringtheweb.model.RoleType;
import com.ringtheweb.model.User;
import com.ringtheweb.model.notification.RegistrationQueryNotification;
import com.ringtheweb.persistence.dao.INotificationDAO;
import com.ringtheweb.service.IUserManager;
import com.ringtheweb.service.exception.NonUniqueLoginException;
import com.ringtheweb.service.exception.RoleNotFoundException;


/**
 * Registration backing-bean.
 * @author ldewavri
 *
 */
@Scope(ScopeType.CONVERSATION)
@Name("register")
public class RegisterAction  implements Serializable {


    /** serialVersionUID */
	private static final long serialVersionUID = 1L;

	@In
    private FacesMessages facesMessages;
    
    @In("#{userManager}") IUserManager userManager;
    
    @In("#{notificationDAO}") INotificationDAO notificationDAO;
    
    @Logger Log logger;

    private User newUser;

    private String loginName;
    
    private String firstName;
    
    private String lastName;
    
    private String password;
    
    private String confirm;
    
    private String email;
    
    private PhoneNumber phoneNumber = new PhoneNumber();
    
    private Date dateOfBirth;
    
    
    /* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getMsisdn()
	 */
    public PhoneNumber getPhoneNumber() {
		return phoneNumber;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setMsisdn(java.lang.String)
	 */
	public void setPhoneNumber(PhoneNumber phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getPassword()
	 */
	public String getPassword() {
		return password;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setPassword(java.lang.String)
	 */
	public void setPassword(String password) {
		this.password = password;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getConfirm()
	 */
	public String getConfirm() {
		return confirm;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setConfirm(java.lang.String)
	 */
	public void setConfirm(String confirm) {
		this.confirm = confirm;
	}

    /* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getLoginName()
	 */
    @NotNull
    @Length(min=6,max=15,message="#{messages.register_loginName_invalid}")
	public String getLoginName() {
		return loginName;
	}

   
	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setLoginName(java.lang.String)
	 */
	public void setLoginName(String loginName) {
		this.loginName = loginName;
	}

    /* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getFirstName()
	 */
    @NotNull
    @Length(min=1,max=30,message="#{messages.register_firstName_invalid}") 
	public String getFirstName() {
		return firstName;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setFirstName(java.lang.String)
	 */
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

    /* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getLastName()
	 */
    @NotNull
    @Length(min=1,max=30,message="#{messages.register_lastName_invalid}")
	public String getLastName() {
		return lastName;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setLastName(java.lang.String)
	 */
	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
	@Email(message="#{messages.register_invalid_email}")
	public String getEmail() {
		return email;
	}


	public void setEmail(String email) {
		this.email = email;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#newRegistration()
	 */
	@Begin(join=true)
	public void newRegistration() {
		if (newUser == null) {
			newUser = new User();
		}
		
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#register()
	 */

	public boolean register() {
    	
		// Create user
		newUser.setFirstName(getFirstName());
		newUser.setLastName(getLastName());
		newUser.setLoginName(getLoginName());
		newUser.getPhoneNumbers().add(phoneNumber);
		newUser.setPassword(getPassword());
		newUser.setEmail(email);
		User savedUser = null;
		
		try {
			savedUser = userManager.saveUserInRole(newUser, RoleType.REGISTRED_USER);
		}
		catch(NonUniqueLoginException e) {
			// Login already taken
			facesMessages.addToControl("loginDecoration", "#{messages.register_loginName_taken}");
			return false;
		}
		catch(InvalidStateException e) {
		
			InvalidValue[] invalidValues = e.getInvalidValues();
			for (InvalidValue invalidValue : invalidValues) {
				if (invalidValue.getBeanClass().equals(PhoneNumber.class) ){
					facesMessages.addToControl("phoneNumberValue","#{messages.register_invalid_phoneNumber}");
				}
			}
			return false;
		}
		catch (RoleNotFoundException e) {
			logger.error("Role #0 not found and it should have been created at deployment", RoleType.REGISTRED_USER.name());
		}
		
		RegistrationQueryNotification registrationQueryNotification = new RegistrationQueryNotification(savedUser);
		
		notificationDAO.makePersistent(registrationQueryNotification);
		
		return true;

		//logger.debug("About to login user : '#0' ", getLoginName());
		//credentials.setUsername(getLoginName());
		//credentials.setPassword(clearTextPassword);
        //identity.login();
        //logger.debug("Logged user : '#0' ", getLoginName());
        
    	
    }


	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#getDateOfBirth()
	 */
	public Date getDateOfBirth() {
		return dateOfBirth;
	}

	/* (non-Javadoc)
	 * @see biz.dewavrin.seamphony.session.Register#setDateOfBirth(java.util.Date)
	 */
	public void setDateOfBirth(Date dateOfBirth) {
		this.dateOfBirth = dateOfBirth;
	}


}
